package middleware

import (
	"goravel/app/models"
	"goravel/app/services"
	"goravel/utils/response"

	"github.com/goravel/framework/contracts/http"
	"github.com/goravel/framework/facades"
)

func CheckPermission() http.Middleware {
	return func(ctx http.Context) {
		facades.Log().Info("权限校验开始")

		user, ok := ctx.Value("user").(models.User)
		if !ok {
			facades.Log().Info("权限获取用户失败")
			response.Abort(ctx, http.StatusForbidden, facades.Lang(ctx).Get("errors.failed_to_fetch"))
			return
		}

		if user.ID == 0 {
			facades.Log().Info("权限获取用户失败ID:0")
			response.Abort(ctx, http.StatusForbidden, facades.Lang(ctx).Get("errors.failed_to_fetch"))
			return
		}

		// 超级用户直接放行
		if user.IsRoot == 1 {
			facades.Log().Info("超级用户，权限验证通过")
			ctx.Request().Next()
			return
		}

		// 获取请求路径和方法
		path := ctx.Request().Path()
		method := ctx.Request().Method()

		facades.Log().Infof("请求路径: %s, 方法: %s", path, method)

		//facades.Log().Infof("请求: %s", ctx.Request().All())

		// 使用权限服务检查权限
		permissionService := services.NewPermissionService()
		hasPermission, err := permissionService.CheckUserPermission(user.ID, path, method)

		if err != nil {
			facades.Log().Errorf("权限检查失败: %v", err)
			response.Abort(ctx, http.StatusInternalServerError, "权限检查失败")
			return
		}

		if !hasPermission {
			facades.Log().Infof("用户 %d 没有访问 %s %s 的权限", user.ID, method, path)
			response.Abort(ctx, http.StatusForbidden, facades.Lang(ctx).Get("errors.forbidden"))
			return
		}

		facades.Log().Info("权限验证通过")
		ctx.Request().Next()
	}
}

// CheckPermissionWithKey 检查指定权限键的中间件
func CheckPermissionWithKey(permissionKey string) http.Middleware {
	return func(ctx http.Context) {
		facades.Log().Infof("权限校验开始，权限键: %s", permissionKey)

		user, ok := ctx.Value("user").(models.User)
		if !ok {
			facades.Log().Info("权限获取用户失败")
			response.Abort(ctx, http.StatusForbidden, facades.Lang(ctx).Get("errors.failed_to_fetch"))
			return
		}

		if user.ID == 0 {
			facades.Log().Info("权限获取用户失败ID:0")
			response.Abort(ctx, http.StatusForbidden, facades.Lang(ctx).Get("errors.failed_to_fetch"))
			return
		}

		// 超级用户直接放行
		if user.IsRoot == 1 {
			facades.Log().Info("超级用户，权限验证通过")
			ctx.Request().Next()
			return
		}

		// 检查用户是否有指定权限
		var count int64
		err := facades.Orm().Query().
			Table("users").
			Join("user_roles", "users.id", "=", "user_roles.user_id").
			Join("role_permissions", "user_roles.role_id", "=", "role_permissions.role_id").
			Join("permissions", "role_permissions.permission_id", "=", "permissions.id").
			Where("users.id", user.ID).
			Where("permissions.perm_key", permissionKey).
			Count(&count)

		if err != nil {
			facades.Log().Errorf("权限检查失败: %v", err)
			response.Abort(ctx, http.StatusInternalServerError, "权限检查失败")
			return
		}

		if count == 0 {
			facades.Log().Infof("用户 %d 没有权限: %s", user.ID, permissionKey)
			response.Abort(ctx, http.StatusForbidden, facades.Lang(ctx).Get("errors.forbidden"))
			return
		}

		facades.Log().Info("权限验证通过")
		ctx.Request().Next()
	}
}

// CheckRole 检查用户角色的中间件
func CheckRole(roleName string) http.Middleware {
	return func(ctx http.Context) {
		facades.Log().Infof("角色校验开始，角色: %s", roleName)

		user, ok := ctx.Value("user").(models.User)
		if !ok {
			facades.Log().Info("权限获取用户失败")
			response.Abort(ctx, http.StatusForbidden, facades.Lang(ctx).Get("errors.failed_to_fetch"))
			return
		}

		if user.ID == 0 {
			facades.Log().Info("权限获取用户失败ID:0")
			response.Abort(ctx, http.StatusForbidden, facades.Lang(ctx).Get("errors.failed_to_fetch"))
			return
		}

		// 超级用户直接放行
		if user.IsRoot == 1 {
			facades.Log().Info("超级用户，角色验证通过")
			ctx.Request().Next()
			return
		}

		// 检查用户是否有指定角色
		var count int64
		err := facades.Orm().Query().
			Table("users").
			Join("user_roles", "users.id", "=", "user_roles.user_id").
			Join("roles", "user_roles.role_id", "=", "roles.id").
			Where("users.id", user.ID).
			Where("roles.role_name", roleName).
			Count(&count)

		if err != nil {
			facades.Log().Errorf("角色检查失败: %v", err)
			response.Abort(ctx, http.StatusInternalServerError, "角色检查失败")
			return
		}

		if count == 0 {
			facades.Log().Infof("用户 %d 没有角色: %s", user.ID, roleName)
			response.Abort(ctx, http.StatusForbidden, facades.Lang(ctx).Get("errors.forbidden"))
			return
		}

		facades.Log().Info("角色验证通过")
		ctx.Request().Next()
	}
}
